#include "gui.h"
using namespace errlog;

FormArea::FormArea(QWidget *parent) 
: QWidget(parent) {
	edgeslider = new QSlider(Qt::Horizontal);
	edgeslider->setFocusPolicy(Qt::StrongFocus);
	edgeslider->setTickPosition(QSlider::TicksBothSides);
	edgeslider->setTickInterval(25);
	edgeslider->setSliderPosition(50);
	edgeslider->setSingleStep(1);
	
	pcslider = new QSlider(Qt::Horizontal);
	pcslider->setFocusPolicy(Qt::StrongFocus);
	pcslider->setTickPosition(QSlider::TicksBothSides);
	pcslider->setTickInterval(25);
	pcslider->setSliderPosition(50);
	pcslider->setSingleStep(1);

//	heatmapButton = new QPushButton(tr("Switch Heatmap"),this);
//	connect(heatmapButton, SIGNAL(clicked()), parent, SLOT(switchHeatmap()));
	processButton = new QPushButton(tr("Do it!"),this);
	connect(processButton, SIGNAL(clicked()), parent, SLOT(process()));
	resetButton = new QPushButton(tr("Reset"),this);
	connect(resetButton, SIGNAL(clicked()), parent, SLOT(reset()));

	QBoxLayout *slidersLayout = new QBoxLayout(QBoxLayout::TopToBottom);
	QGridLayout *f;
	QBoxLayout *l;
	QGroupBox *g;

	l = new QBoxLayout(QBoxLayout::TopToBottom);
	l->addWidget(new QLabel("<b>Source/Sink Weight vs. Edge Weight</b>"));
	f = new QGridLayout;
	f->addWidget(new QLabel("Max Source/Sink"),0,0);
	f->addWidget(new QLabel("Max Edge"),0,1,Qt::AlignRight);
	l->addLayout(f);
	l->addWidget(edgeslider);
	l->addWidget(new QLabel("<b>Class Probability</b>"));
	f = new QGridLayout;
	f->addWidget(new QLabel("Max Background"),0,0);
	f->addWidget(new QLabel("Max Object"),0,1,Qt::AlignRight);
	l->addLayout(f);
	l->addWidget(pcslider);
	g = new QGroupBox("Weights",this);
	g->setLayout(l);
	slidersLayout->addWidget(g);

	f = new QGridLayout;
	g = new QGroupBox("Mark and Process",this);
	radioMarkRect = new QRadioButton(tr("Use Rectangle"));
	radioMarkRect->setChecked(true);
	connect(radioMarkRect,SIGNAL(toggled(bool)),parent,SLOT(changeMode(bool)));
	radioMarkDraw = new QRadioButton(tr("Use Brush"));
	f->addWidget(radioMarkRect,0,0);
	f->addWidget(radioMarkDraw,0,1);
	f->addWidget(processButton,1,0,Qt::AlignCenter);
	f->addWidget(resetButton,1,1,Qt::AlignCenter);
	g->setLayout(f);
	g->setLayout(f);
	slidersLayout->addWidget(g);

	g = new QGroupBox("Heatmap Display",this);
	radioHeatmapSeg = new QRadioButton(tr("Segmentation"));
	radioHeatmapSeg->setChecked(true);
	connect(radioHeatmapSeg,SIGNAL(toggled(bool)),parent,SLOT(changeHeatmap(bool)));
	radioHeatmapProb = new QRadioButton(tr("Probabilities"));
	f = new QGridLayout;
	f->addWidget(radioHeatmapSeg,0,0);
	f->addWidget(radioHeatmapProb,0,1);
	g->setLayout(f);

	slidersLayout->addWidget(g);
	slidersLayout->addItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Expanding));
	setLayout(slidersLayout);
}
void FormArea::reset() {
	pcslider->setSliderPosition(50);
	edgeslider->setSliderPosition(50);
	radioHeatmapSeg->setChecked(true);
	radioMarkRect->setChecked(true);
}
void FormArea::updateMarkerView(bool b) {
	if (b) {
		radioMarkRect->setChecked(true);
		radioMarkDraw->setChecked(false);
	} else {
		radioMarkRect->setChecked(false);
		radioMarkDraw->setChecked(true);
	}
}
int FormArea::getEdgeSliderValue() const{
	return edgeslider->sliderPosition();
}
int FormArea::getPcSliderValue() const{
	return pcslider->sliderPosition();
}
RenderArea::RenderArea():
	_bLMB(false),_bRMB(false) {
}
int RenderArea::rescaleX(int x) const{
	int mv = _qoTop->getImageSize().width();
	int mx = width();
	if (x>=mx)
		return mv;
	return rescale(x,((float)mv)/mx);
}
int RenderArea::rescaleY(int y) const {
	int mv = _qoTop->getImageSize().height();
	int my = height();
	if (y>=my)
		return mv;
	return rescale(y,((float)mv)/my);
}
int RenderArea::rescale(int v, float f /*factor*/) const {
	return int((v*f)+.5);
}
void RenderArea::drawRectangle(int ix1, int iy1, int ix2, int iy2) {
	_qoTop->changed();
	QImage	to = _qoTop->getTargetImage();
	int	x1 = std::max(0,std::min(ix1,ix2)),
			x2 = std::min(to.width()-1,std::max(ix1,ix2)),
			y1 = std::max(0,std::min(iy1,iy2)),
			y2 = std::min(to.height()-1,std::max(iy1,iy2));
	QRgb		b = qRgb(255,255,255),
					w = qRgb(0,0,0);
	for (int i = x1; i<=x2; ++i) {
		to.setPixel(i,y1,(i+y1)%4>2?w:b);
		to.setPixel(i,y2,(i+y2)%4>2?w:b);
	}
	for (int i = y1; i<=y2; ++i) {
		to.setPixel(x1,i,(i+x1)%4>2?w:b);
		to.setPixel(x2,i,(i+x2)%4>2?w:b);
	}
	setPixmap(QPixmap::fromImage(to));
}
void RenderArea::mousePressEvent(QMouseEvent *event) {
	if (_qoTop->getMarkerMode()) {
		_qoTop->reset();
		_qoMouseDown.setWidth(event->x());
		_qoMouseDown.setHeight(event->y());
	} else {
		std::stringstream s;
		s<< "x: "<<event->x()<<" y: "<<event->y();
		if (event->button()==Qt::LeftButton) {
			_bLMB = true;
			s<<" Left Button";
		}
		if (event->button()==Qt::RightButton) {
			_bRMB = true;
			s<<" Right Button";
		}
		MAXVERBOSE("mousepress event "+s.str());
		mousePaint(event->x(),event->y());
	}
}
void RenderArea::mouseReleaseEvent(QMouseEvent *event) {
	if (_qoTop->getMarkerMode()) {
		drawRectangle(_qoMouseDown.width(),_qoMouseDown.height(),event->x(),event->y());
		int bottom	= rescaleY(std::min(_qoMouseDown.height(),event->y())),
				top			= rescaleY(std::max(_qoMouseDown.height(),event->y())),
				left		= rescaleX(std::min(_qoMouseDown.width(),event->x())),
				right		= rescaleX(std::max(_qoMouseDown.width(),event->x())),
				mx			= _qoTop->getImageSize().width(),
				my			= _qoTop->getImageSize().height();
		for (int x = 0; x<mx; ++x)
		for (int y = 0; y<my; ++y) {
			if (x<left || x>right || y<bottom || y>top)
				_qoTop->setTrimapPoint(x,y,Trimap::background);
			else
				_qoTop->setTrimapPoint(x,y,Trimap::object);
		}
	} else {
		std::stringstream s;
		s<< "x: "<<event->x()<<" y: "<<event->y();
	if (event->button()==Qt::LeftButton) {
			_bLMB = false;
			s<<" Left Button";
		}
		if (event->button()==Qt::RightButton) {
			_bRMB = false;
			s<<" Right Button";
		}
		MAXVERBOSE("mouserelease event "+s.str());
	}
}
void RenderArea::mouseMoveEvent(QMouseEvent *event) {
	if (_qoTop->getMarkerMode()) {
		drawRectangle(_qoMouseDown.width(),_qoMouseDown.height(),event->x(),event->y());
	} else {
		std::ostringstream s;
		s<< "x: "<<event->x()<<" y: "<<event->y()<< " lmb: "<< _bLMB << " rmb: "<< _bRMB;
		MAXVERBOSE("mousemove event "+s.str());
		mousePaint(event->x(),event->y());
	}
}
void RenderArea::setTop(MainWindow *top) {
	_qoTop = top;
}

void RenderArea::mousePaint(int x, int y) {
	_qoTop->changed();
	assert(_qoTop);
	Trimap::obu v = _bLMB && _bRMB ?Trimap::unknown:_bLMB?Trimap::object:Trimap::background;
	QImage	to = pixmap()->toImage(),
					from = _qoTop->getTargetImage();
	QRgb pix = qRgba(0,0,0,255);
	bool set = false;
	switch (v) {
	case Trimap::object:
		pix = qRgba(255,0,0,255);
		set = true;
		break;
	case Trimap::background:
		pix = qRgba(0,0,255,255);
		set = true;
		break;
	default:
		break;
	}
	for (int i = std::max(0,x-2); i<std::min(x+2,pixmap()->width());++i)
	for (int j = std::max(0,y-2); j<std::min(y+2,pixmap()->height());++j)
		if (set)
			to.setPixel(i,j,pix);
		else
			to.setPixel(i,j,from.pixel(i,j));
	setPixmap(QPixmap::fromImage(to));
	for (int i = std::max(0,rescaleX(x-2)); i<std::min(rescaleX(x+2),_qoTop->getImageSize().width());++i)
	for (int j = std::max(0,rescaleY(y-2)); j<std::min(rescaleY(y+2),_qoTop->getImageSize().height());++j)
		_qoTop->setTrimapPoint(i,j,v);
}

MainWindow::MainWindow() {
	_oModel = new Gmd2Model();
	_bMarkerMode = true;
	_bShowHeatmap = true;
	QWidget *widget = new QWidget;
	setCentralWidget(widget);

	renderArea = new RenderArea;
	renderArea->setBackgroundRole(QPalette::Base);
	renderArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
	renderArea->setScaledContents(true);
	renderArea->setTop(this);
	heatmapArea = new QLabel;
	heatmapArea->setBackgroundRole(QPalette::Base);
	heatmapArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
	heatmapArea->setScaledContents(true);

	objectonlyArea = new QLabel;
	objectonlyArea->setBackgroundRole(QPalette::Base);
	objectonlyArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
	objectonlyArea->setScaledContents(true);

	formArea = new FormArea(this);

	QGridLayout *layout = new QGridLayout;
	layout->setMargin(5);
	layout->addWidget(formArea,0,1);
	layout->addWidget(renderArea,0,0);
	layout->addWidget(heatmapArea,1,0);
	layout->addWidget(objectonlyArea,1,1);
	widget->setLayout(layout);

	createActions();
	createMenus();

	statusBar()->showMessage(tr("Please open a file"));

	setWindowTitle(tr("GraphCut"));

/*	setMinimumSize(160, 160);
	resize(480, 320);*/
	open();
}
bool MainWindow::getMarkerMode() {
	return _bMarkerMode;
}
void MainWindow::initialiseFile(QString qsFileName) {
	if (_qoSourceImage.load(qsFileName) && !_qoSourceImage.isNull()) {
		MAXVERBOSE("image "+qsFileName.toStdString()+" loaded");
/* INITIALISE MEMBER VARS */
		formArea->reset();
		reset();
	} else
		WARNING("unable to load image " + qsFileName.toStdString());
}
void MainWindow::displayImage() {
	MAXVERBOSE("display image");
	renderArea->setPixmap(QPixmap::fromImage(_qoTargetImage));
	renderArea->setFixedSize(_qoTargetImage.width(),_qoTargetImage.height());
	heatmapArea->setFixedSize(_qoTargetImage.width(),_qoTargetImage.height());
	objectonlyArea->setFixedSize(_qoTargetImage.width(),_qoTargetImage.height());
	resize(sizeHint());
}
void MainWindow::setTrimapPoint(int x, int y,Trimap::obu v) {
	std::ostringstream s;
	s << "x: "<<x<<" y: "<<y << " v: "<<v;
	MAXVERBOSE("setting Trimap at "+s.str());
	_oTrimap.setXY(x,y,v);
}
/*void MainWindow::switchHeatmap () {
	if (_bShowHeatmap) {
		heatmapArea->setPixmap(QPixmap::fromImage(_oProbs.toGrayScale()));
		_bShowHeatmap = false;
	} else {
		heatmapArea->setPixmap(QPixmap::fromImage(_oSegmentation.toHeatmap()));
		_bShowHeatmap = true;
	}
}*/
void MainWindow::open() {
	QString qsFileName = QFileDialog::getOpenFileName(this,
		tr("Open Image"), "", tr("Image Files (*.png *.jpg *.bmp)"));
	if (!qsFileName.isEmpty()) {
		VERBOSE("Invoked File|Open "+ qsFileName.toStdString());
		initialiseFile(qsFileName);
	} else
		VERBOSE("no file was chosen for opening");
}

void MainWindow::saveSeg() {
	QString qsFileName = QFileDialog::getSaveFileName(this,
		tr("Save Image"), "untitled.png", tr("Image Files (*.png *.jpg *.bmp)"));
	VERBOSE("Invoked File|SaveSeg " + qsFileName.toStdString());
	if (!qsFileName.isEmpty()) {
		QRgb tmp;
		QImage i = _qoSourceImage.convertToFormat(QImage::Format_ARGB32);
		for (int x = 0; x<_qoSourceImage.width(); ++x) {
			for (int y = 0; y<_qoSourceImage.height(); ++y) {
				tmp = _qoSourceImage.pixel(x,y);
				i.setPixel(x,y,qRgba(qRed(tmp),qGreen(tmp),qBlue(tmp),_oSegmentation.getXY(x,y)));
			}
		}
		i.save(qsFileName);
	}
}
void MainWindow::saveTri() {
	QString qsFileName = QFileDialog::getSaveFileName(this,
		tr("Save Trimap"), "trimap.png", tr("PNG Files (*.png)"));
	VERBOSE("Invoked File|SaveTri " + qsFileName.toStdString());
	_oTrimap.toFile(qsFileName.toStdString());
}

void MainWindow::reset() {
	_bChanged = false;
	_bInitialised = false;
	MAXVERBOSE("Invoked <b>Reset</b>");
	int w = _qoSourceImage.width(), h= _qoSourceImage.height(),mw = 600, mh=400;
	std::ostringstream s;
	_oTrimap.resize(w, h);
	_oModel->reset();
	if (w>1.5*h) {
		mh = int(600./w*h);
	} else {
		mw = int(400./h*w);
	}
	s<<w<<" "<<h<<" "<<mw<<" "<<mh;
	MAXVERBOSE(s.str());
	_qoTargetImage = _qoSourceImage.convertToFormat(QImage::Format_ARGB32).scaled(mw,mh);
	s<<"x: "<<_oTrimap.getMaxX()<<" y: "<<_oTrimap.getMaxY();
	MAXVERBOSE("Trimap has size "+s.str());
	saveSegAct->setEnabled(false);
	saveTriAct->setEnabled(true);
	statusBar()->showMessage(tr("Please mark object/background"));
	displayImage();
	heatmapArea->setPixmap(QPixmap());
	objectonlyArea->setPixmap(QPixmap());
}
void MainWindow::displayHeatmap() {
	if (_bShowHeatmap)
		heatmapArea->setPixmap(QPixmap::fromImage(_oSegmentation.toHeatmap()));
	else
		heatmapArea->setPixmap(QPixmap::fromImage(_oProbs.toGrayScale()));
}
void MainWindow::changeHeatmap(bool b) {
	_bShowHeatmap = b;
	displayHeatmap();
}
void MainWindow::changeMode() {
	changeMode(!_bMarkerMode);
}
void MainWindow::changeMode(bool b) {
	MAXVERBOSE("Invoked <b>changeMode</b>");
	if (_bMarkerMode != b)
		reset();
	_bMarkerMode = b;
	formArea->updateMarkerView(_bMarkerMode);
}
void MainWindow::process() {
	statusBar()->showMessage(tr("Processing... please wait!"));
	VERBOSE("Invoked <b>Process</b>");
	if (_qoSourceImage.isNull()) {
		QMessageBox::warning(this,tr("Load Image first"),tr("Please load an image and mark it before processing."), QMessageBox::Ok,QMessageBox::NoButton);
	} else if (!isInitialised() && _oTrimap.getCount(Trimap::object)==0) {
		QMessageBox::warning(this,tr("Please mark the object"),tr("Please mark the object. Hit the left mouse button over the object for doing so or use the rectange Tool."), QMessageBox::Ok,QMessageBox::NoButton);
	statusBar()->showMessage(tr("Please mark object and background!"));
	} else if (!isInitialised() && _oTrimap.getCount(Trimap::background)==0) {
		QMessageBox::warning(this,tr("Please mark the background"),tr("Please mark the background. Hit the right mouse button over the background for doing so."), QMessageBox::Ok,QMessageBox::NoButton);
		statusBar()->showMessage(tr("Please mark object and background!"));
 } else {
		int w = _qoTargetImage.size().width(),
				h = _qoTargetImage.size().height();
		statusBar()->showMessage(tr("Please wait! Processing..."));
		_oModel->setImage(Image(_qoSourceImage));
		_oModel->setEdgeWeight(formArea->getEdgeSliderValue()/100.);
		_oModel->setSosiWeight(1. - _oModel->getEdgeWeight());
		_oModel->setClassProbs(formArea->getPcSliderValue()/100.,1-(formArea->getPcSliderValue()/100.));
		if (hasChanged()) {
			_oModel->train(_oTrimap);
			initialised();
			_bChanged = false;
		} else
			VERBOSE("don't train");
		if (getMarkerMode()) {
			_bMarkerMode = false;
			formArea->updateMarkerView(_bMarkerMode);
			_oTrimap.resize(_oTrimap.getWidth(), _oTrimap.getHeight()); //clearing Trimap for calculating
		}
		GraphCut g(Image(_qoSourceImage), _oTrimap, _oModel);
		_oSegmentation = g.process();
		_oProbs = g.getProbs();
		_oProbs.stretch();
		QRgb tmp;
		_qoTargetImage = _qoSourceImage.convertToFormat(QImage::Format_ARGB32);
		QImage objectonly(_qoSourceImage.width(),_qoSourceImage.height(),QImage::Format_ARGB32);
		for (int x = 0; x<_qoSourceImage.width(); ++x) {
			for (int y = 0; y<_qoSourceImage.height(); ++y) {
				tmp = _qoSourceImage.pixel(x,y);
				if (_oSegmentation.getXY(x,y)<125) {
					_qoTargetImage.setPixel(x,y,qRgb(qRed(tmp),qGreen(tmp),255));
				} else {
					_qoTargetImage.setPixel(x,y,qRgb(255,qGreen(tmp),qBlue(tmp)));
				}
				objectonly.setPixel(x,y,qRgba(qRed(tmp),qGreen(tmp),qBlue(tmp),_oSegmentation.getXY(x,y)));
			}
		}
		objectonlyArea->setPixmap(QPixmap::fromImage(objectonly));
		_qoTargetImage = _qoTargetImage.scaled(w,h);
		displayImage();
		displayHeatmap();
		saveSegAct->setEnabled(true);
		statusBar()->showMessage(tr("DONE! Save segmentation or continue marking object/background"));
	}
}

void MainWindow::about() {
	MAXVERBOSE("Invoked <b>Help|About</b>");
	QMessageBox::about(this, tr("About"),
		tr("Some fancy about text."));
}

#ifdef DEBUG
void MainWindow::loglvl() {
	MAXVERBOSE("Invoked <b>Debug|Loglevel</b>");
	QStringList items;
	items << tr("Maxverbose") << tr("Verbose") << tr("Warning") << tr("Error")<<tr("Critical");
	bool ok;
	QString item = QInputDialog::getItem(this, tr("Set loglevel"),tr("Loglevel:"), items, ErrorCtr::getInstance()->getLogLevel(), false, &ok);
	if (ok && !item.isEmpty()) {
		if(item.toStdString()=="Maxverbose")			ErrorCtr::getInstance()->setLogLevel(errlog::maxverbose);
		else if(item.toStdString()=="Verbose")		ErrorCtr::getInstance()->setLogLevel(errlog::verbose);
		else if(item.toStdString()=="Warning")		ErrorCtr::getInstance()->setLogLevel(errlog::warning);
		else if(item.toStdString()=="Error")			ErrorCtr::getInstance()->setLogLevel(errlog::error);
		else if(item.toStdString()=="Critical")		ErrorCtr::getInstance()->setLogLevel(errlog::critical);
	}
}
void MainWindow::chgModel() {
	MAXVERBOSE("Invoked <b>Debug|Model</b>");
	QStringList items;
	items << tr("Simplemodel") << tr("Nearest Neighbour") << tr("GMD") << tr("GMD2") << tr("FANN");
	bool ok;
	QString item = QInputDialog::getItem(this, tr("Change Model"),tr("Use:"), items, 0, false, &ok);
	if (ok && !item.isEmpty()) {
		if(item.toStdString()=="Simplemodel") {
			delete _oModel;
			_oModel = new SimpleModel();
		} else if(item.toStdString()=="Nearest Neighbour") {
			delete _oModel;
			_oModel = new NNModel();
		} else if(item.toStdString()=="GMD") {
			delete _oModel;
			_oModel = new GmdModel();
		} else if(item.toStdString()=="GMD2") {
			delete _oModel;
			_oModel = new Gmd2Model();
		} else if(item.toStdString()=="FANN") {
			delete _oModel;
			_oModel = new FannModel();
		}
		reset();
	}
}
#endif

void MainWindow::createActions() {
	openAct = new QAction(tr("&Open..."), this);
	openAct->setShortcut(tr("Ctrl+O"));
	openAct->setStatusTip(tr("Open an existing file"));
	connect(openAct, SIGNAL(triggered()), this, SLOT(open()));

	saveSegAct = new QAction(tr("&Save segmentation"), this);
	saveSegAct->setShortcut(tr("Ctrl+S"));
	saveSegAct->setStatusTip(tr("Save the segmentation to disk"));
	saveSegAct->setEnabled(false);
	connect(saveSegAct, SIGNAL(triggered()), this, SLOT(saveSeg()));

	saveTriAct = new QAction(tr("&Save Trimap"), this);
	saveTriAct->setShortcut(tr("Ctrl+T"));
	saveTriAct->setStatusTip(tr("Save the Trimap to disk"));
	saveTriAct->setEnabled(false);
	connect(saveTriAct, SIGNAL(triggered()), this, SLOT(saveTri()));

	exitAct = new QAction(tr("E&xit"), this);
	exitAct->setShortcut(tr("Ctrl+Q"));
	exitAct->setStatusTip(tr("Exit the application"));
	connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

	resetAct = new QAction(tr("&Reset"), this);
	resetAct->setShortcut(tr("Ctrl+R"));
	resetAct->setStatusTip(tr("Reset to input image"));
	connect(resetAct, SIGNAL(triggered()), this, SLOT(reset()));

	changeModeAct = new QAction(tr("&Change mode"), this);
	changeModeAct->setShortcut(tr("Ctrl+M"));
	changeModeAct->setStatusTip(tr("Switch marker tools"));
	connect(changeModeAct, SIGNAL(triggered()), this, SLOT(changeMode()));

	processAct = new QAction(tr("&Process"), this);
	processAct->setShortcut(tr("Ctrl+P"));
	processAct->setStatusTip(tr("Process the image and create Segmentation"));
	connect(processAct, SIGNAL(triggered()), this, SLOT(process()));

	aboutAct = new QAction(tr("&About"), this);
	aboutAct->setStatusTip(tr("Show the application's About box"));
	connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
#ifdef DEBUG
	loglvlAct = new QAction(tr("&Loglevel"), this);
	loglvlAct->setStatusTip(tr("Set the current loglevel"));
	connect(loglvlAct, SIGNAL(triggered()), this, SLOT(loglvl()));
	chgModelAct = new QAction(tr("&Model"), this);
	chgModelAct->setStatusTip(tr("Change used model"));
	connect(chgModelAct, SIGNAL(triggered()), this, SLOT(chgModel()));
#endif
}

void MainWindow::createMenus() {
	fileMenu = menuBar()->addMenu(tr("&File"));
	fileMenu->addAction(openAct);
	fileMenu->addAction(saveSegAct);
	fileMenu->addAction(saveTriAct);
	fileMenu->addSeparator();
	fileMenu->addAction(exitAct);

	editMenu = menuBar()->addMenu(tr("&Edit"));
	editMenu->addAction(resetAct);
	editMenu->addAction(changeModeAct);
	editMenu->addSeparator();
	editMenu->addAction(processAct);

	helpMenu = menuBar()->addMenu(tr("&Help"));
	helpMenu->addAction(aboutAct);

#ifdef DEBUG
	debugMenu = menuBar()->addMenu(tr("&Debug"));
	debugMenu->addAction(loglvlAct);
	debugMenu->addAction(chgModelAct);
#endif
}
QSize MainWindow::getImageSize() {
	return _qoSourceImage.size();
}
QImage MainWindow::getTargetImage() {
	return _qoTargetImage;
}
bool MainWindow::hasChanged() const{
	return _bChanged;
}
void MainWindow::changed() {
	_bChanged = true;
}
bool MainWindow::isInitialised() const{
	return _bInitialised;
}
void MainWindow::initialised() {
	_bInitialised = true;
}
